💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    로딩 중이에요... 🐣

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    02 요약정리 | ✅ 저자: 이유정(박사)

    네이버 블로그 크롤링 방법 정리

    네이버 블로그는 iframe 구조JavaScript 렌더링이 포함된 형태이기 때문에, 크롤링을 위해서는 상황에 맞는 도구를 사용하는 것이 중요합니다. 다음은 실제 블로그 본문을 추출하는 방법과 도구별 적용 기준을 정리한 내용입니다.


    ✅ 주요 과제 정리

    • 네이버 블로그 리뷰 수집

    • iframe 구조 대응 필요

    • 특정 키워드 필터링

    • 불필요 텍스트(예: "블로그기자단") 제거(cleaning)


    📁 디렉토리 구조 예시

    project_root/
    │
    ├── naver_crawler/
    │   ├── __init__.py
    │   ├── naver_blog_scrap_selenium.py
    │   └── naver_blog_scrap_request.py
    │
    └── notebook.ipynb  # Jupyter 실습 노트북
    

    📌 도구별 특징 및 적용 기준

    1. requests

    • 용도: 정적인 HTML, JSON, XML 등 서버에서 직접 요청해 가져올 때 사용

    • 한계: JavaScript 렌더링된 DOM 결과는 수집 불가

    import requests
    response = requests.get("https://api.example.com/data")
    data = response.json()
    

    2. BeautifulSoup

    • 용도: HTML/XML 파싱 → 원하는 태그, 텍스트 추출

    • 한계: 크롤링 기능 없음 (requests와 함께 사용)

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, "html.parser")
    title = soup.find("div", class_="title").text
    

    3. selenium

    • 용도: JS 기반 동적 페이지 렌더링 처리, 사용자 인터랙션 구현

    • 적합: iframe 내부 데이터, 클릭/로그인/스크롤 동작 필요할 때

    • 단점: 느리고 리소스 많이 소모

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    driver.get("https://example.com")
    driver.find_element(By.ID, "loadButton").click()
    html = driver.page_source
    

    🧼 텍스트 정제 함수 (cleaning)

    import re
    import unicodedata
    
    def clean_text(text):
        text = "".join(c for c in text if not unicodedata.category(c).startswith("C"))
        text = re.sub(r"[ \t\n\r\f\v]+", " ", text)
        return text.strip()
    

    🧭 Selenium 기반 블로그 본문 수집

    # 파일명 예시: naver_crawler/naver_blog_scrap_selenium.py
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.chrome.service import Service
    from bs4 import BeautifulSoup
    import re
    from webdriver_manager.chrome import ChromeDriverManager
    import unicodedata
    
    
    def clean_text(text):
        text = "".join(c for c in text if not unicodedata.category(c).startswith("C"))
        text = re.sub(r"[ \t\n\r\f\v]+", " ", text)
        return text.strip()
    
    
    def crawl_naver_blog(url):
        options = webdriver.ChromeOptions()
        options.add_argument('--headless')
        service = Service(ChromeDriverManager().install())
        driver = webdriver.Chrome(service=service, options=options)
        driver.get(url)
    
        iframe_element = driver.find_element(By.ID, "mainFrame")
        driver.switch_to.frame(iframe_element)
    
        driver.find_element(By.ID, "post-area")
        res = driver.page_source
        driver.quit()
    
        soup = BeautifulSoup(res, "html.parser")
        content = soup.find("div", {"class": "se-main-container"})
        if content is None:
            content = soup.find("div", {"id": "post-area"})
        span_tag = content.find("span", text=re.compile("블로그기자단"))
        if span_tag:
            span_tag.decompose()
        content = clean_text(content.text)
        return content
    

    ⚡ requests 기반 iframe 크롤링 (JS 렌더링 필요 없음)

    # 파일명 예시: naver_crawler/naver_blog_scrap_request.py
    import requests
    from bs4 import BeautifulSoup
    import re
    import unicodedata
    
    
    def clean_text(text):
        text = "".join(c for c in text if not unicodedata.category(c).startswith("C"))
        text = re.sub(r"[ \t\n\r\f\v]+", " ", text)
        return text.strip()
    
    
    def crawl_naver_blog_by_requests(url):
        res = requests.get(url)
        root_url = "https://blog.naver.com"
    
        if 'id="mainFrame"' in res.text:
            soup = BeautifulSoup(res.text, "html.parser")
            iframe = soup.find("iframe", {"id": "mainFrame"})
            iframe_src = iframe["src"]
            res = requests.get(root_url + iframe_src)
    
        soup = BeautifulSoup(res.text, "html.parser")
        content = soup.find("div", {"class": "se-main-container"})
        if content is None:
            content = soup.find("div", {"id": "post-area"})
        span_tag = content.find("span", text=re.compile("블로그기자단"))
        if span_tag:
            span_tag.decompose()
        content = clean_text(content.text)
        return content
    

    🔍 네이버 검색결과에서 블로그 리뷰 추출

    # 파일명 예시: naver_crawler/naver_blog_scrap_request.py
    
    def find_review_article(location: str, keyword: str):
        import requests
        from bs4 import BeautifulSoup
    
        url = f"https://search.naver.com/search.naver?sm=tab_hty.top&ssc=tab.blog.all&query={location}+{keyword}+리뷰"
        res = requests.get(url)
        soup = BeautifulSoup(res.text, "html.parser")
    
        title_link = soup.find_all("a", class_="title_link")
        review_list = []
        for t_l in title_link:
            title = t_l.text
            href = t_l["href"]
            if keyword in title:
                review_list.append((title, href))
    
        return review_list
    

    🧪 Jupyter 사용 예

    # selenium 기반 블로그 본문 추출 예시
    from naver_crawler.naver_blog_scrap_selenium import crawl_naver_blog
    crawl_naver_blog("https://blog.naver.com/gangbuk_official/223177144192")
    
    # requests 기반 예시
    from naver_crawler.naver_blog_scrap_request import crawl_naver_blog_by_requests
    crawl_naver_blog_by_requests("https://blog.naver.com/gangbuk_official/223177144192")
    
    # 리뷰 링크 목록 추출
    from naver_crawler.naver_blog_scrap_request import find_review_article
    find_review_article("강북구", "맛집")
    

    🖼️ 1) Jupyter vscode

    이미지

    🖼️ 2) Jupyter Browser

    jupyter notebook --no-browser --port 8888
    

    이미지


    ✅ 요약

    • 정적 HTML/JSONrequests

    • HTML 파싱BeautifulSoup

    • JS 렌더링 필요selenium

    • iframe 대응 → iframe URL 추출 후 별도 요청 or Selenium으로 진입

    • 텍스트 정제clean_text() 함수 활용

    블로그 본문이 iframe + JS 렌더링 구조일 경우, Selenium 사용이 가장 확실합니다.


    TOP
    preload preload